package com.example.config;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.context.EnvironmentAware;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;

/**
 * 数据库初始化器
 * 在数据源Bean初始化之前检查数据库是否存在，如果不存在则自动创建
 */
@Slf4j
@Component
public class DatabaseInitializer implements BeanFactoryPostProcessor, EnvironmentAware {
    
    private Environment environment;
    
    @Override
    public void setEnvironment(Environment environment) {
        this.environment = environment;
    }
    
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        try {
            String datasourceUrl = environment.getProperty("spring.datasource.url");
            String username = environment.getProperty("spring.datasource.username");
            String password = environment.getProperty("spring.datasource.password");
            Boolean autoCreateDatabase = environment.getProperty("auto-table.auto-create-database", Boolean.class, true);
            
            checkAndCreateDatabase(datasourceUrl, username, password, autoCreateDatabase);
        } catch (Exception e) {
            log.error("数据库初始化失败", e);
            throw new RuntimeException("数据库初始化失败: " + e.getMessage(), e);
        }
    }
    
    private void checkAndCreateDatabase(String datasourceUrl, String username, String password, Boolean autoCreateDatabase) {
        if (!autoCreateDatabase) {
            log.info("自动创建数据库功能已禁用");
            return;
        }
        
        log.info("========================================");
        log.info("检查数据库是否存在");
        log.info("========================================");
        
        try {
            // 从完整的URL中提取数据库名称
            String databaseName = extractDatabaseName(datasourceUrl);
            if (databaseName == null || databaseName.isEmpty()) {
                log.warn("无法从URL中提取数据库名称: {}", datasourceUrl);
                return;
            }
            
            // 构建不包含数据库名的连接URL（连接到MySQL服务器）
            String serverUrl = buildServerUrl(datasourceUrl);
            
            log.info("数据库名称: {}", databaseName);
            log.info("服务器URL: {}", serverUrl);
            
            // 连接到MySQL服务器（不指定数据库）
            try (Connection conn = DriverManager.getConnection(serverUrl, username, password);
                 Statement stmt = conn.createStatement()) {
                
                // 检查数据库是否存在
                if (!isDatabaseExists(stmt, databaseName)) {
                    log.warn("数据库 {} 不存在，开始创建...", databaseName);
                    createDatabase(stmt, databaseName);
                    log.info("✓ 数据库 {} 创建成功", databaseName);
                } else {
                    log.info("✓ 数据库 {} 已存在", databaseName);
                }
            }
            
            log.info("========================================");
            log.info("数据库检查完成");
            log.info("========================================");
        } catch (Exception e) {
            log.error("检查和创建数据库时出错", e);
            throw new RuntimeException("数据库初始化失败", e);
        }
    }
    
    /**
     * 从JDBC URL中提取数据库名称
     * 例如: jdbc:mysql://localhost:3306/mp_auto_table?xxx -> mp_auto_table
     */
    private String extractDatabaseName(String url) {
        try {
            // 移除jdbc:mysql://前缀
            String temp = url.substring(url.indexOf("://") + 3);
            
            // 找到第一个/后的内容
            int slashIndex = temp.indexOf('/');
            if (slashIndex == -1) {
                return null;
            }
            
            temp = temp.substring(slashIndex + 1);
            
            // 移除参数部分（?后面的内容）
            int questionIndex = temp.indexOf('?');
            if (questionIndex != -1) {
                temp = temp.substring(0, questionIndex);
            }
            
            return temp.trim();
        } catch (Exception e) {
            log.error("提取数据库名称失败", e);
            return null;
        }
    }
    
    /**
     * 构建服务器连接URL（不包含数据库名）
     * 例如: jdbc:mysql://localhost:3306/mp_auto_table?xxx -> jdbc:mysql://localhost:3306?xxx
     */
    private String buildServerUrl(String url) {
        try {
            // 找到数据库名称的位置
            String prefix = url.substring(0, url.indexOf("://") + 3);
            String temp = url.substring(url.indexOf("://") + 3);
            
            int slashIndex = temp.indexOf('/');
            if (slashIndex == -1) {
                return url;
            }
            
            String serverPart = temp.substring(0, slashIndex);
            
            // 获取参数部分
            String paramsPart = "";
            int questionIndex = temp.indexOf('?');
            if (questionIndex != -1) {
                paramsPart = temp.substring(questionIndex);
            }
            
            return prefix + serverPart + paramsPart;
        } catch (Exception e) {
            log.error("构建服务器URL失败", e);
            return url;
        }
    }
    
    /**
     * 检查数据库是否存在
     */
    private boolean isDatabaseExists(Statement stmt, String databaseName) throws Exception {
        String checkSql = "SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME = '" + databaseName + "'";
        var rs = stmt.executeQuery(checkSql);
        return rs.next();
    }
    
    /**
     * 创建数据库
     */
    private void createDatabase(Statement stmt, String databaseName) throws Exception {
        String createSql = "CREATE DATABASE IF NOT EXISTS `" + databaseName + "` " +
                          "DEFAULT CHARACTER SET utf8mb4 " +
                          "DEFAULT COLLATE utf8mb4_general_ci";
        
        log.info("执行SQL: {}", createSql);
        stmt.execute(createSql);
    }
}
